/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include ".\ssi_commandserver.h"

#include <string>
#include <iostream>

#define  SSI_OPEN_REQUEST      131
#define  SSI_LINE_REQUEST      132
#define  SSI_RESPONSE_OUTPUT   133
#define  SSI_COMMAND           134
#define  SSI_BYE               135
#define  SSI_ACTION_REQUEST    136
#define  SSI_ACTION_RESPONSE   137

#define  SSI_ERROR_OUTPUT      140
#define  SSI_WARNING_OUTPUT    141
#define  SSI_FAILURE_OUTPUT    142

#define  SSI_FILE_REQUEST			 150			 
#define  SSI_FILE_RESPONSE     151
#define  SSI_FILE_ERROR        152

#define  SSI_RSP_PORT          200
#define  SSI_FLAG_REQUEST      210
#define  SSI_FLAG_RESPONSE     211


#define  SSI_VAR_RQST          300
#define  SSI_VAR_RSP           301

#define  SSI_DBG_RQST          500
#define  SSI_DBG_RSP           501
#define  SSI_DBG_STEP          510

#define  SSI_BPT_ADD           520
#define  SSI_BPT_RMV           521

#define  SSI_DBG_JMP           530
#define  SSI_DBG_OUT           531

#define  SSI_DBG_EVAL          540

#define  SSI_DBG_GOCTR         550
#define  SSI_DBG_TOLIN         551

#define  DEBUG_BIT             1
#define  ARGS_BIT              2


CCommandServer::CCommandServer(void)
{
  m_Arguments = "";
  bArgs = 0;
}

CCommandServer::~CCommandServer(void)
{
  if(aSock.myHandle != 0){

    // This is required, as described in http://www.port80software.com/200ok/archive/2004/12/07/205.aspx
    // Essentially, allows for FIN handshake, then goes into TIME_WAIT before ending
    //CSocketSSI::CloseSocket(aSock);
    CSocketSSI::Disconnect(aSock.myHandle);
    aSock.myHandle = 0;
  }
}

int CCommandServer::Init(const String& sHost, int iPort, ssi_stream& out)
{
  int nPort = iPort;
	//int retval = 0;
	//CSocketSSI::Init();

	string data;
  string pcHost = sHost.Str();

  //if(argc > 1) {
	//	pcHost = argv[1];
	//	cout << "Host: " << pcHost << endl;
  //}
  //
	//if(argc > 2){
	//  sscanf(argv[2], "%d", &nPort);
	//	printf("Port: %d\n", nPort);
  //}
  
	////////////////////// INIT /////////////////
	
	SSI_ADDR RemoteAddr = aSock.LookupAddress(pcHost.c_str());
	if(RemoteAddr == INADDR_NONE){
    String s;
    s.Format("[Socket] Error*** Could not resolve address: %s", pcHost.c_str());
    out.ErrorDisp(s.Str(), 1);
    //cout << "ERROR*** Could not resolve address: " << pcHost << endl;
    //out.d
		return 0;
	}

	SSI_SOCKET sd = aSock.Connect(RemoteAddr, nPort);
	if(sd == INVALID_SOCKET){
		//cout << "ERROR*** Could not connect to " << pcHost << endl; 
    String s;
    s.Format("[Socket] Error*** Could not connect to %s", pcHost.c_str());
    out.ErrorDisp(s.Str(), 1);
		return 0;
	}

	aSock.myHandle = sd;

	char nm[1024];
	gethostname(nm, 1024);
	char* IP_addr = CSocketSSI::IPFromName(nm);
	//cout << "Host Name is: " << nm << " [" << IP_addr << "]" << endl;
  //out.Format("[Socket] Host Name: %s [%s]", nm, IP_addr);

	CSockCmd aCmd;
	//CSockCmd Ret;
	aCmd.Set(SSI_OPEN_REQUEST, 0, 0);

	//cout << "Sending open request..." << endl;
  //out.Format("[Socket] Sending open request...");
	aCmd.SendMe(aSock);

	// This will be a new socket port
	aCmd.ReadMe(aSock);
	if(aCmd.ID == SSI_RSP_PORT){
		nPort = *(int*)(aCmd.Data);
		SSI_SOCKET newHandle = aSock.Connect(RemoteAddr, nPort);
		
		//out.Format("New Handle: %d [Port = %d]", newHandle, nPort);
		
		if(newHandle == INVALID_SOCKET){
			//cout << "ERROR*** Could not connect to " << pcHost << endl; 
      String s;
      s.Format("[Socket] Error*** Could not connect to new port on %s (%d)", pcHost.c_str(), CSocketSSI::GetLastError());
      out.ErrorDisp(s.Str(), 1);
			aCmd.Set(RSP_NACK, 0, 0);
			aCmd.SendMe(aSock);
      CSocketSSI::Disconnect(sd);
			return 0;
		}
		aCmd.Set(RSP_ACK, 0, 0);
		aCmd.SendMe(aSock);
		aSock.myHandle = newHandle;
	}

  CSocketSSI::Disconnect(sd);

	//cout << "New port accepted" << endl;
  //out.Format("[Socket] New port accepted");

	if(!aCmd.ReadMe(aSock)){
		//cout << "Could not read action request" << endl;
    String s;
    s.Format("[Socket] Error*** Could not read action request (%d)", CSocketSSI::GetLastError());
    out.ErrorDisp(s.Str(), 1);
		return 0;
	}
  return 1;
}

int CCommandServer::runScript(const String& sFile, int bDebug, ssi_stream& out)
{
    CSockCmd aCmd;
    int flags = 0;
    string s = sFile.Str();
		aCmd.Set(SSI_ACTION_RESPONSE, s.length(), s.c_str());

		if(!aCmd.SendMe(aSock)){
      out.ErrorDisp("[Socket] Error*** Could not send action response", 1);
			return 0;
		}

		if(!aCmd.ReadMe(aSock)){
      out.ErrorDisp("[Socket] Error*** Could not read ACK response", 1);
			return 0;
		}

		if(aCmd.ID != RSP_ACK){
      out.ErrorDisp("[Socket] Error*** Action ACK response not received", 1);
			return 0;
		}

		// Flag processing
		if(!aCmd.ReadMe(aSock)){
      out.ErrorDisp("[Socket] Error*** Could not read flag request", 1);
			return 0;
		}

    if(aCmd.ID != SSI_FLAG_REQUEST){
      out.ErrorDisp("[Socket] Error*** Flag request expected", 1);
			return 0;
    }

    if(bDebug){
			flags = flags | DEBUG_BIT;
		}
    if(bArgs){
      flags = flags | ARGS_BIT;
    }

		aCmd.Set(SSI_FLAG_RESPONSE, sizeof(flags), (char*)(&flags));

		if(!aCmd.SendMe(aSock)){
      out.ErrorDisp("[Socket] Error*** Could not send flag response", 1);
			return 0;
		}

		if(!aCmd.ReadMe(aSock)){
      out.ErrorDisp("[Socket] Error*** Could not read flag ACK response", 1);
			return 0;
		}

		if(aCmd.ID != RSP_ACK){
      out.ErrorDisp("[Socket] Error*** Flag ACK response not received", 1);
			return 0;
		}

    if(bArgs){
     	if(!aCmd.ReadMe(aSock)){
        out.ErrorDisp("[Socket] Error*** Could not read arg request", 1);
	  		return 0;
		  }

      if(aCmd.ID != SSI_ARGS_REQUEST){
        out.ErrorDisp("[Socket] Error*** Args request expected", 1);
		    return 0;
      }


      s = m_Arguments.Str();
      aCmd.Set(SSI_ARGS_RESPONSE, s.length(), s.c_str());
      if(!aCmd.SendMe(aSock)){
        out.ErrorDisp("[Socket] Error*** Could not send arg response", 1);
		    return 0;
	    }

      if(!aCmd.ReadMe(aSock)){
        out.ErrorDisp("[Socket] Error*** Could not read args ACK response", 1);
			  return 0;
		  }

		  if(aCmd.ID != RSP_ACK){
        out.ErrorDisp("[Socket] Error*** Args ACK response not received", 1);
			  return 0;
		  }
    }

    return 1;
}

int CCommandServer::runConsole(ssi_stream& out)
{
  CSockCmd aCmd;
  int flags = 0;

  aCmd.Set(SSI_ACTION_RESPONSE, 0, 0);
	if(!aCmd.SendMe(aSock)){
    out.ErrorDisp("[Socket] Error*** Could not send action response", 1);
		return 0;
	}

	if(!aCmd.ReadMe(aSock)){
    out.ErrorDisp("[Socket] Error*** Could not read ACK response", 1);
		return 0;
	}

	if(aCmd.ID != RSP_ACK){
    out.ErrorDisp("[Socket] Error*** Action ACK response not received", 1);
		return 0;
	}

	// Flag processing
	if(!aCmd.ReadMe(aSock)){
    out.ErrorDisp("[Socket] Error*** Could not read flag response", 1);
		return 0;
	}

	aCmd.Set(SSI_FLAG_RESPONSE, sizeof(flags), (char*)(&flags));

	if(!aCmd.SendMe(aSock)){
    out.ErrorDisp("[Socket] Error*** Could not send flag response", 1);
		return 0;
	}

	if(!aCmd.ReadMe(aSock)){
    out.ErrorDisp("[Socket] Error*** Could not read flag ACK response", 1);
		return 0;
	}

	if(aCmd.ID != RSP_ACK){
    out.ErrorDisp("[Socket] Error*** Flag ACK response not received", 1);
		return 0;
	}
  return 1;
}

int CCommandServer::Loop(ssi_stream& out)
{
  CSockCmd aCmd;
 	aCmd.SequenceCtr = 0;
  char sBuff[4096];
  
	//out.Disp("TEST HERE", 1);
	//std::cout << "Holla\n";

	// Read only this first command
	if(!aCmd.ReadMe(aSock)) return 0;

	while(1){

		//String blah;
		//blah.Format("CMD CODE: %d", aCmd.ID); 
		//out.Disp(blah.Str(), 1);

		if(!aCmd.IsValidSequence()) break;
		if(aCmd.ID == SSI_LINE_REQUEST){
			sBuff[0] = 0;
			//cin.getline(sBuff, 4096);
      out.getline(sBuff, 4096);

			string s = sBuff;
			string s2;
			int ind = 0;

			//if(strcmp(sBuff, "clear_ctr") == 0){
			//	cout << "Clearing counter" << endl;
			//	aCmd.SequenceCtr = 0;
			//	sBuff[0] = 0;
			//}

			aCmd.Set(SSI_COMMAND, (int)strlen(sBuff), sBuff);
			if(!aCmd.SendMe(aSock)) break;

			if(!aCmd.ReadMe(aSock)) break;
			if(!aCmd.IsValidSequence()) break;
			if(aCmd.ID != RSP_ACK){
				if(aCmd.Size > 0){
          String s;
          s.Format("[Socket] Error*** : %s", aCmd.Data);
          out.ErrorDisp(s.Str(), 1);
          //cout << "Error Message: " << aCmd.Data << endl;
				}
				aCmd.Set(SSI_BYE, 0, 0);
				aCmd.SendMe(aSock);
				break;
			}

			if(!aCmd.ReadMe(aSock)) break;
			if(!aCmd.IsValidSequence()) break;

		}else if(aCmd.ID == SSI_FILE_REQUEST){
			string sFile = aCmd.Data;
			FILE* fh = fopen(sFile.c_str(), "rb");
			char buff[4095];
			int iSize = 0;
			while((iSize = fread((void*)buff, 1, 4095, fh)) == 4095){
				aCmd.Set(SSI_FILE_RESPONSE, iSize, buff);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send file data" << endl;
          String s;
          s.Format("[Socket] Error*** Could not send file %s", sFile.c_str());
          out.ErrorDisp(s.Str(), 1);
					return 0;
				}

				if(!aCmd.ReadMe(aSock)) break;
				if(!aCmd.IsValidSequence()) break;
				if(aCmd.ID != RSP_ACK){
					if(aCmd.Size > 0){
            String s;
            s.Format("[Socket] Error*** : %s", aCmd.Data);
            out.ErrorDisp(s.Str(), 1);
						//cout << "Error Message: " << aCmd.Data << endl;
					}
					aCmd.Set(SSI_BYE, 0, 0);
					aCmd.SendMe(aSock);
					break;
				}
			}
			fclose(fh);

			aCmd.Set(SSI_FILE_RESPONSE, iSize, buff);
			if(!aCmd.SendMe(aSock)){
        String s;
        s.Format("[Socket] Error*** Could not send file data (%s)", sFile.c_str());
        out.ErrorDisp(s.Str(), 1);
				//cout << "Could not send file data" << endl;
				return 0;
			}

			if(!aCmd.ReadMe(aSock)) break;
			if(!aCmd.IsValidSequence()) break;
			if(aCmd.ID != RSP_ACK){
				if(aCmd.Size > 0){
          String s;
          s.Format("[Socket] Error*** : %s", aCmd.Data);
          out.ErrorDisp(s.Str(), 1);
					//cout << "Error Message: " << aCmd.Data << endl;
				}
				aCmd.Set(SSI_BYE, 0, 0);
				aCmd.SendMe(aSock);
				break;
			}

			if(iSize > 0){
				aCmd.Set(SSI_FILE_RESPONSE, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send end file data" << endl;
          String s;
          s.Format("[Socket] Error*** : Could not send end of file", sFile.c_str());
          out.ErrorDisp(s.Str(), 1);
					return 0;
				}
			}
			if(!aCmd.ReadMe(aSock)) break;
			if(!aCmd.IsValidSequence()) break;
			if(aCmd.ID != RSP_ACK){
				if(aCmd.Size > 0){
					//cout << "Error Message: " << aCmd.Data << endl;
          String s;
          s.Format("[Socket] Error*** : %s", aCmd.Data);
          out.ErrorDisp(s.Str(), 1);
				}
				aCmd.Set(SSI_BYE, 0, 0);
				aCmd.SendMe(aSock);
				break;
			}

			// Still need to read the next command, dummy
			if(!aCmd.ReadMe(aSock)) break;
			if(!aCmd.IsValidSequence()) break;

		}else if(aCmd.ID == SSI_DBG_RQST){
			//cout << aCmd.Data << endl;
      out.Disp(aCmd.Data, 1);

			char sBuff[4096];
			sBuff[0] = 0;
			//cout << "Enter DEBUG Command: ";
			//cin.getline(sBuff, 4096);
      out.getline(sBuff, 4096);

			string s = sBuff;
			string s2;
			int ind = 0;
			
			if(s == "j"){
				aCmd.Set(SSI_DBG_JMP, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send jump request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug jump request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read jump response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug jump response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}
				
				aCmd.Set(RSP_ACK, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug jump ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

			}else if(s == "o"){
				aCmd.Set(SSI_DBG_OUT, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send jump request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug out request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read jump response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug out response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}
				
				aCmd.Set(RSP_ACK, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug out ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

			}else if((ind = s.find("v ")) >= 0){
				s2 = s.substr(ind+2, s.length());
				aCmd.Set(SSI_VAR_RQST, s2.length(), s2.c_str());
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send variable request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug variable request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read variable response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug variable response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != SSI_VAR_RSP){
					//cout << "Invalid variable response" << endl;
          out.ErrorDisp("[Socket] Error*** Invalid debug variable response", 1);
					aCmd.Set(RSP_NACK, 0, 0);
					aCmd.SendMe(aSock);
				}
        out.DisplayDebugVariable(String(aCmd.Data));
				//cout << " DEBUG: " << aCmd.Data << endl;
				aCmd.Set(RSP_ACK, 0, 0);

				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send variable ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug variable ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}
			}else if((ind = s.find("e ")) >= 0){
				s2 = s.substr(ind+2, s.length());
				aCmd.Set(SSI_DBG_EVAL, s2.length(), s2.c_str());
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send eval request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug eval request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read eval response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug eval response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != RSP_ACK){
					//cout << "Invalid eval response" << endl;
          out.ErrorDisp("[Socket] Error*** Invalid debug eval response", 1);
					aCmd.Set(RSP_NACK, 0, 0);
					aCmd.SendMe(aSock);
				}

				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send eval ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug eval ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}
			}else if((ind = s.find("t ")) >= 0){
				s2 = s.substr(ind+2, s.length());
				aCmd.Set(SSI_DBG_TOLIN, s2.length(), s2.c_str());
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send to line request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug to line request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read to line response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug to line response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != RSP_ACK){
          out.ErrorDisp("[Socket] Error*** Invalid debug to line response", 1);
					//cout << "Invalid to line response" << endl;
					aCmd.Set(RSP_NACK, 0, 0);
					aCmd.SendMe(aSock);
					//CSocketSSI::CleanUp();
				}

				if(!aCmd.SendMe(aSock)){
          out.ErrorDisp("[Socket] Error*** Could not send debug to line ACK", 1);
					//cout << "Could not send to line ACK" << endl;
					CSocketSSI::CleanUp();
					return 0;
				}
			}else if((ind = s.find("g ")) >= 0){
				s2 = s.substr(ind+2, s.length());
				aCmd.Set(SSI_DBG_GOCTR, s2.length(), s2.c_str());
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send go counter request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug go request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read go counter response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug go response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != RSP_ACK){
					//cout << "Invalid go counter response" << endl;
          out.ErrorDisp("[Socket] Error*** Invalid debug go response", 1);
					aCmd.Set(RSP_NACK, 0, 0);
					aCmd.SendMe(aSock);
					//CSocketSSI::CleanUp();
				}

				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send go counter ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug go ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}
			}else if((ind = s.find("+b ")) >= 0){
				s2 = s.substr(ind+2, s.length());
				aCmd.Set(SSI_BPT_ADD, s2.length(), s2.c_str());
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send breakpoint request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug add breakpoint request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read breakpoint response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug add breakpoint response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != RSP_ACK){
          out.ErrorDisp("[Socket] Error*** Debug add breakpoint NACK received", 1);
					//cout << "Breakpoint NACK" << endl;
					CSocketSSI::CleanUp();
					return 0;
				}

				aCmd.Set(RSP_ACK, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug add breakpoint ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}
			}else if((ind = s.find("-b ")) >= 0){
				s2 = s.substr(ind+2, s.length());
				aCmd.Set(SSI_BPT_RMV, s2.length(), s2.c_str());
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send breakpoint removal request" << endl;
          out.ErrorDisp("[Socket] Error*** Debug breakpoint remove request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read breakpoint removal response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug breakpoint remove response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != RSP_ACK){
					//cout << "Breakpoint removal NACK" << endl;
          out.ErrorDisp("[Socket] Error*** Debug remove breakpoint NACK received", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				aCmd.Set(RSP_ACK, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug breakpoint remove ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

			}else{
				aCmd.Set(SSI_DBG_STEP, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send step command" << endl;
          out.ErrorDisp("[Socket] Error*** Debug step request failed", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(!aCmd.ReadMe(aSock)){
					//cout << "Could not read debug step response" << endl;
          out.ErrorDisp("[Socket] Error*** Could not read debug step response", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				if(aCmd.ID != RSP_ACK){
					//cout << "Debug Step NACK" << endl;
          out.ErrorDisp("[Socket] Error*** Debug step NACK received", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				aCmd.Set(RSP_ACK, 0, 0);
				if(!aCmd.SendMe(aSock)){
					//cout << "Could not send ACK" << endl;
          out.ErrorDisp("[Socket] Error*** Could not send debug step ACK", 1);
					CSocketSSI::CleanUp();
					return 0;
				}

				// Step through
			}

			// Read the next command... this is in the major loop
			if(!aCmd.ReadMe(aSock)) return 0;
		}else	if(aCmd.ID == RSP_NACK){
			//cout << "NACK Received" << endl;
      out.ErrorDisp("[Socket] Error*** NACK command received", 1);
			if(aCmd.Size > 0){
				//cout << "  Message: " << aCmd.Data << endl;
        String s;
        s.Format("[Socket] Error*** NACK data: %s", aCmd.Data);
        out.ErrorDisp(s.Str(), 1);
			}

		}else if(aCmd.ID == SSI_RESPONSE_OUTPUT || aCmd.ID == SSI_ERROR_OUTPUT || aCmd.ID == SSI_WARNING_OUTPUT || aCmd.ID == SSI_FAILURE_OUTPUT){
			if(aCmd.Size > 0){
				///cout << aCmd.Data;
        if(aCmd.ID == SSI_RESPONSE_OUTPUT){
          out.Disp(aCmd.Data, 0);
        }else if(aCmd.ID == SSI_ERROR_OUTPUT){
          out.ErrorDisp(aCmd.Data, 0);
        }else if(aCmd.ID == SSI_WARNING_OUTPUT){
          out.WarningDisp(aCmd.Data, 0);
        }else if(aCmd.ID == SSI_FAILURE_OUTPUT){
          out.FailureDisp(aCmd.Data, 0);
        }

			}
			aCmd.Set(RSP_ACK, 0, 0);
			if(!aCmd.SendMe(aSock)) break;
			if(!aCmd.ReadMe(aSock)) break;
			if(!aCmd.IsValidSequence()) break;
		}else if(aCmd.ID == SSI_BYE){
      out.ErrorDisp("[Socket] Shutdown initiated by client", 1);
      break;
    }
	}
	CSocketSSI::CleanUp();
  return 1;
}

void CCommandServer::killConnection(void)
{
  //printf("DISCONNECTING\n");
  CSocketSSI::Disconnect(aSock.myHandle);
  //printf("CLOSING\n");
  //CSocketSSI::CloseSocket(aSock.myHandle);
  //printf("CLEANUP\n");
  CSocketSSI::CleanUp();
}

void CCommandServer::setArguments(const String& Args)
{
  m_Arguments = Args;
  bArgs = 1;
}
